/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "record_command_handler.h"
#include "utils_log.h"
#include <sstream>
#include <iomanip>
#include <ctime>

namespace El {
namespace Protocol {

void RecordCommandHandler::RegisterMethodHandlers(
    std::unordered_map<std::string, std::function<nlohmann::json(const std::string &, const nlohmann::json &)>>
        &handlers)
{
    // 注册录像相关方法
    handlers["records.search"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleRecordsSearch(id, params);
    };

    handlers["records.getList"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleRecordsGetList(id, params);
    };

    handlers["records.getInfo"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleRecordsGetInfo(id, params);
    };

    // 注册回放相关方法
    handlers["playback.start"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandlePlaybackStart(id, params);
    };

    handlers["playback.stop"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandlePlaybackStop(id, params);
    };

    handlers["playback.pause"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandlePlaybackPause(id, params);
    };

    handlers["playback.resume"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandlePlaybackResume(id, params);
    };

    handlers["playback.seek"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandlePlaybackSeek(id, params);
    };

    handlers["playback.setSpeed"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandlePlaybackSetSpeed(id, params);
    };
}

nlohmann::json RecordCommandHandler::HandleRecordsSearch(const std::string &id, const nlohmann::json &params)
{
    try {
        // 参数验证
        if (!params.contains("channel") || !params["channel"].is_number()) {
            return CreateErrorResponse(id, -32602, "Invalid params: channel is required and must be number");
        }

        if (!params.contains("start_time") || !params["start_time"].is_string()) {
            return CreateErrorResponse(id, -32602, "Invalid params: start_time is required and must be string");
        }

        if (!params.contains("end_time") || !params["end_time"].is_string()) {
            return CreateErrorResponse(id, -32602, "Invalid params: end_time is required and must be string");
        }

        int32_t channel = params["channel"];
        std::string start_time_str = params["start_time"];
        std::string end_time_str = params["end_time"];
        
        // 可选参数
        std::string event_type = params.value("event_type", "all");
        int stream_type = params.value("stream_type", 0);
        
        // 转换时间格式
        auto start_time = parseTimeString(start_time_str);
        auto end_time = parseTimeString(end_time_str);
        
        // 创建搜索实例
        std::lock_guard<std::mutex> lock(mutex_);
        if (!search_instance_) {
            search_instance_ = El::Record::IRecordSearch::create();
            if (!search_instance_) {
                EL_ERROR("[WEB_RECORD_SEARCH] Failed to create search instance");
                return CreateErrorResponse(id, -32603, "Failed to create search instance");
            }
        } else {
        }
        
        // 执行搜索
        bool success = false;
        if (event_type == "image") {
            success = search_instance_->searchImage(channel, start_time, end_time);
        } else {
            success = search_instance_->searchVideo(channel, start_time, end_time);
        }
        
        if (!success) {
            EL_ERROR("[WEB_RECORD_SEARCH] Search operation failed for channel: {}, event_type: {}", channel, event_type);
            return CreateErrorResponse(id, -32603, "Search operation failed");
        }
        
        // 生成搜索ID
        std::string search_id = "search_" + std::to_string(std::time(nullptr)) + "_" + std::to_string(channel);
        search_sessions_[search_id] = event_type; // 保存搜索类型
        
        nlohmann::json result = {
            {"search_id", search_id},
            {"channel", channel},
            {"start_time", start_time_str},
            {"end_time", end_time_str},
            {"event_type", event_type},
            {"stream_type", stream_type},
            {"message", "Search initiated successfully"}
        };

        return CreateSuccessResponse(id, result);
    }
    catch (const std::exception &e) {
        EL_ERROR("HandleRecordsSearch error: {}", e.what());
        return CreateErrorResponse(id, -32603, "Internal error: " + std::string(e.what()));
    }
}

nlohmann::json RecordCommandHandler::HandleRecordsGetList(const std::string &id, const nlohmann::json &params)
{
    try {
        // 参数验证
        if (!params.contains("page") || !params["page"].is_number()) {
            return CreateErrorResponse(id, -32602, "Invalid params: page is required and must be number");
        }

        if (!params.contains("page_size") || !params["page_size"].is_number()) {
            return CreateErrorResponse(id, -32602, "Invalid params: page_size is required and must be number");
        }

        int page = params["page"];
        int page_size = params["page_size"];
        
        // 可选参数
        std::string search_id = params.value("search_id", "");
        std::string sort_by = params.value("sort_by", "start_time");
        std::string sort_order = params.value("sort_order", "desc");
        
        if (page < 0 || page_size <= 0 || page_size > 1000) {
            return CreateErrorResponse(id, -32602, "Invalid pagination parameters");
        }
        
        std::lock_guard<std::mutex> lock(mutex_);
        if (!search_instance_) {
            EL_ERROR("[WEB_RECORD_GETLIST] No active search instance");
            return CreateErrorResponse(id, -32603, "No active search instance");
        }
        
        // 确定搜索类型
        std::string search_type = "video"; // 默认为视频
        if (!search_id.empty() && search_sessions_.find(search_id) != search_sessions_.end()) {
            search_type = search_sessions_[search_id];
        } else {
            EL_WARN("[WEB_RECORD_GETLIST] Search_id not found or empty, using default search_type: {}", search_type);
            if (!search_id.empty()) {
            }
        }
        
        nlohmann::json records = nlohmann::json::array();
        int32_t found = 0;
        bool has_more = false;
        
        if (search_type == "image") {
            // 获取图片文件列表
            std::vector<El::Record::ImageFileInfo> image_files;
            bool success = search_instance_->findNextImage(page_size, found, image_files);
            
            if (success) {
                for (const auto &file : image_files) {
                    records.push_back(imageFileInfoToJson(file));
                }
                
                // 检查是否还有更多数据
                std::vector<El::Record::ImageFileInfo> next_batch;
                int32_t next_found = 0;
                has_more = search_instance_->findNextImage(1, next_found, next_batch) && next_found > 0;
            }
        } else {
            // 获取视频文件列表
            std::vector<El::Record::VideoFileInfo> video_files;
            bool success = search_instance_->findNextVideo(page_size, found, video_files);
            
            if (success) {
                for (const auto &file : video_files) {
                    records.push_back(videoFileInfoToJson(file));
                    EL_DEBUG("[WEB_RECORD_GETLIST] Added video file: {}", file.fileName);
                }
                
                // 检查是否还有更多数据
                std::vector<El::Record::VideoFileInfo> next_batch;
                int32_t next_found = 0;
                has_more = search_instance_->findNextVideo(1, next_found, next_batch) && next_found > 0;
            } else {
                EL_ERROR("[WEB_RECORD_GETLIST] findNextVideo failed");
            }
        }

        nlohmann::json result = {
            {"records", records},
            {"total_count", found},
            {"page", page},
            {"page_size", page_size},
            {"has_more", has_more},
            {"search_id", search_id},
            {"sort_by", sort_by},
            {"sort_order", sort_order}
        };
        
        return CreateSuccessResponse(id, result);
    }
    catch (const std::exception &e) {
        EL_ERROR("[WEB_RECORD_GETLIST] HandleRecordsGetList error: {}", e.what());
        return CreateErrorResponse(id, -32603, "Internal error: " + std::string(e.what()));
    }
}

nlohmann::json RecordCommandHandler::HandleRecordsGetInfo(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("HandleRecordsGetInfo called with params: {}", params.dump());

    try {
        // 参数验证
        if (!params.contains("file_id") || !params["file_id"].is_string()) {
            return CreateErrorResponse(id, -32602, "Invalid params: file_id is required and must be string");
        }

        std::string file_id = params["file_id"];
        
        // 这里简化实现，实际应该通过文件ID查询详细信息
        // 由于base/record模块没有直接的按ID查询接口，
        // 实际实现中可能需要解析文件ID获取文件路径，然后读取文件信息
        
        nlohmann::json result = {
            {"file_id", file_id},
            {"message", "File info retrieval not fully implemented"},
            {"note", "This requires additional file metadata management"}
        };

        return CreateSuccessResponse(id, result);
    }
    catch (const std::exception &e) {
        EL_ERROR("HandleRecordsGetInfo error: {}", e.what());
        return CreateErrorResponse(id, -32603, "Internal error: " + std::string(e.what()));
    }
}

nlohmann::json RecordCommandHandler::HandlePlaybackStart(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("HandlePlaybackStart called with params: {}", params.dump());

    try {
        // 参数验证
        if (!params.contains("file_id") || !params["file_id"].is_string()) {
            return CreateErrorResponse(id, -32602, "Invalid params: file_id is required and must be string");
        }

        std::string file_id = params["file_id"];
        
        // 可选参数
        std::string protocol = params.value("protocol", "webrtc");
        int start_position = params.value("start_position", 0);
        float speed = params.value("speed", 1.0f);
        
        // 创建回放实例
        auto playback = El::Record::IPlayback::create();
        if (!playback) {
            return CreateErrorResponse(id, -32603, "Failed to create playback instance");
        }
        
        // 配置回放（这里简化为使用文件路径，实际应从file_id解析）
        bool config_success = playback->config(file_id);
        if (!config_success) {
            return CreateErrorResponse(id, -32603, "Failed to configure playback with file: " + file_id);
        }
        
        // 生成回放ID
        std::string playback_id = "playback_" + std::to_string(std::time(nullptr)) + "_" + file_id;
        
        // 设置播放速度
        if (speed != 1.0f) {
            playback->setSpeed(speed);
        }
        
        // 启动回放（这里需要实际的回调处理，简化实现）
        auto frame_callback = [playback_id](El::Media::MediaFramePtr &frame) {
            (void)frame; // 避免未使用参数警告
            // 这里应该将帧数据发送到流媒体服务
            EL_DEBUG("Playback frame received for session: {}", playback_id);
        };
        
        bool start_success = playback->start(frame_callback);
        if (!start_success) {
            return CreateErrorResponse(id, -32603, "Failed to start playback");
        }
        
        // 如果指定了起始位置，进行定位
        if (start_position > 0) {
            playback->seekByTime(static_cast<uint32_t>(start_position));
        }
        
        // 保存回放实例
        std::lock_guard<std::mutex> lock(mutex_);
        playback_instances_[playback_id] = playback;

        nlohmann::json result = {
            {"playback_id", playback_id},
            {"status", "started"},
            {"file_id", file_id},
            {"protocol", protocol},
            {"start_position", start_position},
            {"speed", speed},
            {"message", "Playback started successfully"}
        };

        return CreateSuccessResponse(id, result);
    }
    catch (const std::exception &e) {
        EL_ERROR("HandlePlaybackStart error: {}", e.what());
        return CreateErrorResponse(id, -32603, "Internal error: " + std::string(e.what()));
    }
}

nlohmann::json RecordCommandHandler::HandlePlaybackStop(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("HandlePlaybackStop called with params: {}", params.dump());

    try {
        // 参数验证
        if (!params.contains("playback_id") || !params["playback_id"].is_string()) {
            return CreateErrorResponse(id, -32602, "Invalid params: playback_id is required and must be string");
        }

        std::string playback_id = params["playback_id"];
        
        std::lock_guard<std::mutex> lock(mutex_);
        auto it = playback_instances_.find(playback_id);
        if (it == playback_instances_.end()) {
            return CreateErrorResponse(id, -32602, "Playback session not found: " + playback_id);
        }
        
        // 停止回放
        bool success = it->second->stop();
        if (!success) {
            return CreateErrorResponse(id, -32603, "Failed to stop playback");
        }
        
        // 移除回放实例
        playback_instances_.erase(it);

        nlohmann::json result = {
            {"playback_id", playback_id},
            {"status", "stopped"},
            {"message", "Playback stopped successfully"}
        };

        return CreateSuccessResponse(id, result);
    }
    catch (const std::exception &e) {
        EL_ERROR("HandlePlaybackStop error: {}", e.what());
        return CreateErrorResponse(id, -32603, "Internal error: " + std::string(e.what()));
    }
}

nlohmann::json RecordCommandHandler::HandlePlaybackPause(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("HandlePlaybackPause called with params: {}", params.dump());

    try {
        // 参数验证
        if (!params.contains("playback_id") || !params["playback_id"].is_string()) {
            return CreateErrorResponse(id, -32602, "Invalid params: playback_id is required and must be string");
        }

        std::string playback_id = params["playback_id"];
        
        std::lock_guard<std::mutex> lock(mutex_);
        auto it = playback_instances_.find(playback_id);
        if (it == playback_instances_.end()) {
            return CreateErrorResponse(id, -32602, "Playback session not found: " + playback_id);
        }
        
        // 暂停回放
        bool success = it->second->pause();
        if (!success) {
            return CreateErrorResponse(id, -32603, "Failed to pause playback");
        }

        nlohmann::json result = {
            {"playback_id", playback_id},
            {"status", "paused"},
            {"message", "Playback paused successfully"}
        };

        return CreateSuccessResponse(id, result);
    }
    catch (const std::exception &e) {
        EL_ERROR("HandlePlaybackPause error: {}", e.what());
        return CreateErrorResponse(id, -32603, "Internal error: " + std::string(e.what()));
    }
}

nlohmann::json RecordCommandHandler::HandlePlaybackResume(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("HandlePlaybackResume called with params: {}", params.dump());

    try {
        // 参数验证
        if (!params.contains("playback_id") || !params["playback_id"].is_string()) {
            return CreateErrorResponse(id, -32602, "Invalid params: playback_id is required and must be string");
        }

        std::string playback_id = params["playback_id"];
        
        std::lock_guard<std::mutex> lock(mutex_);
        auto it = playback_instances_.find(playback_id);
        if (it == playback_instances_.end()) {
            return CreateErrorResponse(id, -32602, "Playback session not found: " + playback_id);
        }
        
        // 恢复回放
        bool success = it->second->resume();
        if (!success) {
            return CreateErrorResponse(id, -32603, "Failed to resume playback");
        }

        nlohmann::json result = {
            {"playback_id", playback_id},
            {"status", "resumed"},
            {"message", "Playback resumed successfully"}
        };

        return CreateSuccessResponse(id, result);
    }
    catch (const std::exception &e) {
        EL_ERROR("HandlePlaybackResume error: {}", e.what());
        return CreateErrorResponse(id, -32603, "Internal error: " + std::string(e.what()));
    }
}

nlohmann::json RecordCommandHandler::HandlePlaybackSeek(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("HandlePlaybackSeek called with params: {}", params.dump());

    try {
        // 参数验证
        if (!params.contains("playback_id") || !params["playback_id"].is_string()) {
            return CreateErrorResponse(id, -32602, "Invalid params: playback_id is required and must be string");
        }

        if (!params.contains("position") || !params["position"].is_number()) {
            return CreateErrorResponse(id, -32602, "Invalid params: position is required and must be number");
        }

        std::string playback_id = params["playback_id"];
        uint32_t position = params["position"];
        
        // 可选参数
        std::string seek_type = params.value("seek_type", "absolute");
        
        std::lock_guard<std::mutex> lock(mutex_);
        auto it = playback_instances_.find(playback_id);
        if (it == playback_instances_.end()) {
            return CreateErrorResponse(id, -32602, "Playback session not found: " + playback_id);
        }
        
        // 执行定位
        bool success = it->second->seekByTime(position);
        if (!success) {
            return CreateErrorResponse(id, -32603, "Failed to seek playback position");
        }

        nlohmann::json result = {
            {"playback_id", playback_id},
            {"status", "seeked"},
            {"position", position},
            {"seek_type", seek_type},
            {"message", "Playback seeked successfully"}
        };

        return CreateSuccessResponse(id, result);
    }
    catch (const std::exception &e) {
        EL_ERROR("HandlePlaybackSeek error: {}", e.what());
        return CreateErrorResponse(id, -32603, "Internal error: " + std::string(e.what()));
    }
}

nlohmann::json RecordCommandHandler::HandlePlaybackSetSpeed(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("HandlePlaybackSetSpeed called with params: {}", params.dump());

    try {
        // 参数验证
        if (!params.contains("playback_id") || !params["playback_id"].is_string()) {
            return CreateErrorResponse(id, -32602, "Invalid params: playback_id is required and must be string");
        }

        if (!params.contains("speed") || !params["speed"].is_number()) {
            return CreateErrorResponse(id, -32602, "Invalid params: speed is required and must be number");
        }

        std::string playback_id = params["playback_id"];
        float speed = params["speed"];
        
        if (speed <= 0) {
            return CreateErrorResponse(id, -32602, "Invalid speed value: must be greater than 0");
        }
        
        std::lock_guard<std::mutex> lock(mutex_);
        auto it = playback_instances_.find(playback_id);
        if (it == playback_instances_.end()) {
            return CreateErrorResponse(id, -32602, "Playback session not found: " + playback_id);
        }
        
        // 设置回放速度
        bool success = it->second->setSpeed(speed);
        if (!success) {
            return CreateErrorResponse(id, -32603, "Failed to set playback speed");
        }

        nlohmann::json result = {
            {"playback_id", playback_id},
            {"status", "speed_set"},
            {"speed", speed},
            {"message", "Playback speed set successfully"}
        };

        return CreateSuccessResponse(id, result);
    }
    catch (const std::exception &e) {
        EL_ERROR("HandlePlaybackSetSpeed error: {}", e.what());
        return CreateErrorResponse(id, -32603, "Internal error: " + std::string(e.what()));
    }
}

std::chrono::system_clock::time_point RecordCommandHandler::parseTimeString(const std::string &timeStr)
{
    // 支持多种时间格式
    // 格式1: ISO 8601 (2023-12-01T12:30:45Z)
    // 格式2: Unix timestamp (1701428445)
    // 格式3: 简化格式 (2023-12-01 12:30:45)
    
    // 先尝试解析Unix时间戳
    try {
        size_t pos;
        long long timestamp = std::stoll(timeStr, &pos);
        if (pos == timeStr.length()) {
            // 纯数字，当作Unix时间戳处理
            return std::chrono::system_clock::from_time_t(timestamp);
        }
    } catch (...) {
        // 不是数字，继续其他格式解析
    }
    
    // 尝试解析ISO 8601格式或简化格式
    std::tm tm = {};
    std::istringstream ss(timeStr);
    
    // 尝试多种格式
    const char* formats[] = {
        "%Y-%m-%dT%H:%M:%SZ",  // ISO 8601
        "%Y-%m-%dT%H:%M:%S",   // ISO 8601 without Z
        "%Y-%m-%d %H:%M:%S",   // 简化格式
        "%Y-%m-%d"             // 只有日期
    };
    
    for (size_t i = 0; i < sizeof(formats)/sizeof(formats[0]); ++i) {
        const char* format = formats[i];
        ss.clear();
        ss.str(timeStr);
        ss >> std::get_time(&tm, format);
        if (!ss.fail()) {
            // 检查是否是UTC时间（带Z后缀）
            if (i == 0 || timeStr.find('Z') != std::string::npos) {
                // UTC时间，使用timegm
                return std::chrono::system_clock::from_time_t(timegm(&tm));
            } else {
                // 本地时间，使用mktime
                return std::chrono::system_clock::from_time_t(std::mktime(&tm));
            }
        }
    }
    
    // 如果所有格式都失败，返回当前时间
    EL_WARN("Failed to parse time string: {}, using current time", timeStr);
    return std::chrono::system_clock::now();
}

std::string RecordCommandHandler::formatTimePoint(const std::chrono::system_clock::time_point &tp)
{
    auto time_t = std::chrono::system_clock::to_time_t(tp);
    std::stringstream ss;
    ss << std::put_time(std::gmtime(&time_t), "%Y-%m-%dT%H:%M:%SZ");
    return ss.str();
}

nlohmann::json RecordCommandHandler::videoFileInfoToJson(const El::Record::VideoFileInfo &info)
{
    return nlohmann::json{
        {"file_name", info.fileName},
        {"channel", info.ch},
        {"start_time", formatTimePoint(info.start)},
        {"end_time", formatTimePoint(info.end)},
        {"size", info.size},
        {"event_type", info.event},
        {"stream_type", info.type},
        {"has_audio", info.hasAudio},
        {"fps", info.fps},
        {"bit_rate", info.bitRate},
        {"type", "video"}
    };
}

nlohmann::json RecordCommandHandler::imageFileInfoToJson(const El::Record::ImageFileInfo &info)
{
    return nlohmann::json{
        {"file_name", info.fileName},
        {"channel", info.ch},
        {"time", formatTimePoint(info.time)},
        {"size", info.size},
        {"event_type", info.event},
        {"width", info.width},
        {"height", info.height},
        {"has_thumbnail", info.hasThumbnail},
        {"type", "image"}
    };
}

} // namespace Protocol
} // namespace El